home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
051-075
/
disk_074
/
less
/
signal.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
4KB
|
211 lines
/*
* Routines dealing with signals.
*
* A signal usually merely causes a bit to be set in the "signals" word.
* At some convenient time, the mainline code checks to see if any
* signals need processing by calling psignal().
* An exception is made if we are reading from the keyboard when the
* signal is received. Some operating systems will simply call the
* signal handler and NOT return from the read (with EINTR).
* To handle this case, we service the interrupt directly from
* the handler if we are reading from the keyboard.
*/
#include "less.h"
#ifndef amiga
#include <signal.h>
#endif
#include <setjmp.h>
/*
* The type of signal handler functions.
* Usually int, although it should be void.
*/
typedef int HANDLER;
/*
* "sigs" contains bits indicating signals which need to be processed.
*/
public int sigs;
#define S_INTERRUPT 01
#ifdef SIGTSTP
#define S_STOP 02
#endif
extern int reading;
extern char *first_cmd;
extern jmp_buf main_loop;
/*
* Interrupt signal handler.
*/
static HANDLER
interrupt()
{
#ifdef amiga
printf("interrupt\n");
#else
SIGNAL(SIGINT, interrupt);
sigs |= S_INTERRUPT;
if (reading)
psignals();
#endif
}
#ifdef SIGTSTP
/*
* "Stop" (^Z) signal handler.
*/
static HANDLER
stop()
{
SIGNAL(SIGTSTP, stop);
sigs |= S_STOP;
if (reading)
psignals();
}
#endif
/*
* Set up the signal handlers.
*/
public void
init_signals()
{
#ifdef amiga
#else
(void) SIGNAL(SIGINT, interrupt);
#ifdef SIGTSTP
(void) SIGNAL(SIGTSTP, stop);
#endif
#endif
}
/*
* Process any signals we have recieved.
* A received signal cause a bit to be set in "sigs".
*/
public void
psignals()
`{
#ifdef amiga
#else
register int tsignals;
tsignals = sigs;
sigs = 0;
if (tsignals == 0)
return;
dropout(); /* Discard any buffered output */
#ifdef SIGTSTP
if (tsignals & S_STOP)
{
/*
* Clean up the terminal.
*/
#ifdef SIGTTOU
SIGNAL(SIGTTOU, SIG_IGN);
#endif
lower_left();
clear_eol();
flush();
raw_mode(0);
#ifdef SIGTTOU
SIGNAL(SIGTTOU, SIG_DFL);
#endif
SIGNAL(SIGTSTP, SIG_DFL);
#if SIGSETMASK
/*
* This system will not allow us to send a
* stop signal (SIGTSTP) to ourself
* while we are in the signal handler, like maybe now.
* (This can be the case if we are reading; see comment above.)
* So we ask the silly system for permission to do so.
*/
sigsetmask(0);
#endif
kill(getpid(), SIGTSTP);
/*
* ... Bye bye. ...
* Hopefully we'll be back later and resume here...
* Reset the terminal and arrange to repaint the
* screen when we get back to the main command loop.
*/
SIGNAL(SIGTSTP, stop);
raw_mode(1);
first_cmd = "r";
longjmp(main_loop, 1);
}
#endif
if (tsignals & S_INTERRUPT)
{
bell();
/*
* {{ You may wish to replace the bell() with
* error("Interrupt"); }}
*/
}
longjmp(main_loop, 1);
#endif
}
/*
* Pass the specified command to a shell to be executed.
* Like plain "system()", but handles resetting terminal modes, etc.
*/
public void
lsystem(cmd)
char *cmd;
{
int inp;
/*
* Print the command which is to be executed.
*/
lower_left();
clear_eol();
puts("!");
puts(cmd);
puts("\n");
#ifdef amiga
Execute(cmd, 0L, 0L);
#else
/*
* De-initialize the terminal and take out of raw mode.
*/
deinit();
flush();
raw_mode(0);
/*
* Restore signals to their defaults.
*/
SIGNAL(SIGINT, SIG_DFL);
#ifdef SIGTSTP
SIGNAL(SIGTSTP, SIG_DFL);
#endif
/*
* Pass the command to the system to be executed.
*/
inp = dup(0);
close(0);
open("/dev/tty", 0);
system(cmd);
close(0);
dup(inp);
close(inp);
/*
* Reset signals, raw mode, etc.
*/
init_signals();
raw_mode(1);
init();
#endif
}